package org.wzl._360mallbackend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.wzl._360mallbackend.dao.CategoryDao;
import org.wzl._360mallbackend.dao.CommodityDao;
import org.wzl._360mallbackend.entity.Category;
import org.wzl._360mallbackend.entity.Commodity;
import org.wzl._360mallbackend.service.CategoryService;

import java.util.*;

@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryDao , Category> implements CategoryService  {

    @Autowired
    private CommodityDao commodityDao;

    /**
     * 获取所有下属分类
     * @param id 分类id
     * @return 所有下属分类
     */
    @Override
    public List<Category> getAllCategoryById(Integer id) {
        List<Category> categoryList = this.baseMapper.selectList(null);
        Map<Integer , Integer> idAndTopIdMap = new HashMap<>();
        categoryList.forEach(category -> idAndTopIdMap.put(category.getId() , category.getTopId()));
        List<Category> res = new ArrayList<>();
        for (Category category : categoryList) {
            if (category.getId() != id && deepId(category.getId(), id, idAndTopIdMap)) {
                res.add(category);
            }
        }
        return res;
    }
    //TODO 算法需要改进，该算法需要O(n^n)
    private boolean deepId(Integer curId , Integer targetId,Map<Integer , Integer> idAndTopIdMap) {
        if (curId == targetId) {
            return true;
        }
        if (curId == -1) {
            return false;
        }
        return deepId(idAndTopIdMap.get(curId) , targetId , idAndTopIdMap);
    }

    /**
     * 获取同级所有相同的分类和对应的商品
     * @param categoryName 分类名称
     * @return
     */
    @Override
    public Map<String, Object> getCommodityByCategoryName(String categoryName) {
        //当搜索为空时
        if (categoryName == null || categoryName.equals("")) {
            Map<String , Object> resultMap = new HashMap<>();
            List<Category> nextLevelCategories = this.getNextLevelCategories(-1);
            List<Commodity> commodities = commodityDao.selectList(null);
            resultMap.put("category" , nextLevelCategories);
            resultMap.put("commodities" , commodities);
            return resultMap;
        } else {
            //根据名字获取category子分类
            QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("name" , categoryName);
            Category category = this.baseMapper.selectOne(queryWrapper);
            if (!Objects.isNull(category)) {
                List<Category> allCategoryById = this.getSameLevelCategory(category.getId());
                if (!Objects.isNull(allCategoryById)) {
                    Integer topId = category.getTopId();
                    List<Category> containTopIdCategories = this.getContainTopIdCategories(allCategoryById, topId);

                    //下属所有菜单
                    List<Category> ids = new ArrayList<>();
                    for (Category cate : containTopIdCategories) {
                        List<Category> list = this.getAllCategoryById(cate.getId());
                        ids.addAll(list);
                    }

                    List<Category> nextLevelCategories = this.getNextLevelCategories(category.getId());

                    //根据获取到的子分类再获取商品
                    List<Commodity> commodityByCategoryIds = commodityDao.getCommodityByCategoryIds(ids);

                    Map<String , Object> resultMap = new HashMap<>();
                    resultMap.put("category" , nextLevelCategories);
                    resultMap.put("commodities" , commodityByCategoryIds);

                    return resultMap;
                } else {
                    return null;
                }
            } else {
                return null;
            }
        }
    }

    @Override
    public List<Category> getNextLevelCategories(Integer id) {
        //TODO redis缓存
        return this.baseMapper.selectList(null)
                .stream()
                .filter(category -> Objects.equals(category.getTopId(), id))
                .toList();
    }

    /**
     * 获取同级分类
     * @param id  分类di
     * @return  同级分类
     */
    private List<Category> getSameLevelCategory(Integer id) {
        //TODO redis缓存
        List<Category> categoryList = this.baseMapper.selectList(null);
        Set<Integer> set = new HashSet<>();
        //BFS
        Queue<Integer> queue = new ArrayDeque<>();
        queue.add(-1);
        set.add(-1);
        boolean flag = false;
        while (!queue.isEmpty()) {
            List<Integer> pollList = new ArrayList<>();
            while (!queue.isEmpty()) {
                pollList.add(queue.poll());
            }
            List<Category> cur = new ArrayList<>();
            for (Integer poll : pollList) {
                for (Category category : categoryList) {
                    if (!set.contains(category.getId())) {
                        if (category.getTopId() == poll) {
                            queue.add(category.getId());
                            set.add(category.getId());
                            if (category.getId() == id) {
                                flag = true;
                            }
                            cur.add(category);
                        }
                    }
                }
            }
            if (flag) {
                return cur;
            }
        }
        return null;
    }

    /**
     * 在所有同级分类中，找出相同父id的分类
     * @param categoryList
     * @return
     */
    private List<Category> getContainTopIdCategories(List<Category> categoryList, Integer topId) {
        List<Category> result = new ArrayList<>();
        for (Category category : categoryList) {
            if (category.getTopId() == topId) {
                result.add(category);
            }
        }
        return result;
    }

}
